2

变量提升:变量的声明写在可以在使用变量之后;
函数提升:函数可以先调用,后声明;

上面先解释了下我理解的这两个概念的定义。要真正理解它们,最好从变量对象的角度出发。引出变量对象的概念,要先理解执行上下文,也就是当控制器执行到可执行代码的时候,就会生成一个执行上下文,也就是代码的执行环境,会产生一个作用域。这个执行上下文的生命周期有两个阶段:创建阶段代码执行阶段

创建阶段就会创建变量对象,创建的过程分三步:

1.建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值
2.先检查有没有函数声明(利用function关键字声明的函数,在变量对象中用函数名作为属性名,属性值是函数内存地址
的引用。如果函数名的引用已经存在,那么会被新的引用覆盖)
3.再检查变量声明,每找到一个变量声明,就在变量对象里用变量名作为属性名,属性值是undefined。如果变量名已经存在,直接跳过,目的是防止把同名的函数被修改成undefined

执行阶段会将变量对象转换为活动对象:

创建完成之后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其他代码。
(在变量对象创建过程中,其中的属性不可访问。只有在执行阶段转为活动对象后,才可以访问其中的内容)

先来一个简单的例子:

function foo(){
    a = 2;
    function a(){
        console.log("函数")
    }
    console.log(a); //2
    var a;
};
foo();

这个例子中,当控制器遇到这段代码时候,会形成一个执行上下文。随后进入到执行上下文的第一个生命周期:创建阶段,此时,执行创建变量对象的三个步骤。

  • 由于没有参数。直接进入第二步。
  • 首先检查上下文中有没有function关键字声明的函数,以a为属性名,函数的引用为属性值,添加到变量对象中。
  • 再检查函数声明,发现了变量名a,但是,以a为属性名的属性值已经存在,所以跳过。

接下来进入第二个生命周期:代码执行

a被赋值为2,函数a未被调用。打印a等于2

函数提升也是一个道理,由于变量对象创建过程中会先检查function关键字声明的函数,以该函数的函数名为属性,值为函数地址的引用,添加进变量对象中。

参考:前端基础进阶(三):变量对象详解 关于JavaScript变量提升的理解


nero
4.4k 声望6.4k 粉丝

前端工程师